home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr07 / oleo130s.zip / OLEO130S.TAR / oleo-1.3 / io-x11.c < prev    next >
C/C++ Source or Header  |  1993-03-30  |  59KB  |  2,585 lines

  1. #ifdef HAVE_X11_X_H
  2. /*    Copyright (C) 1992, 1993 Free Software Foundation, Inc.
  3.     
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2, or (at your option)
  7.     any later version.
  8.     
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.     
  14.     You should have received a copy of the GNU General Public License
  15.     along with this software; see the file COPYING.  If not, write to
  16.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18.  
  19. #include  <stdio.h>
  20. #include <ctype.h>
  21. #include <sys/param.h>
  22. #define NeedFunctionPrototypes 0
  23. #include <X11/X.h>
  24. #include <X11/Xlib.h>
  25. #include <X11/Xutil.h>
  26. #include <X11/Xresource.h>
  27. #include <X11/keysym.h>
  28. #include "global.h"
  29. #include "utils.h"
  30. #include "io-generic.h"
  31. #include "io-edit.h"
  32. #include "io-utils.h"
  33. #include "io-term.h"
  34. #include "cmd.h"
  35. #include "window.h"
  36. #include "line.h"
  37. #include "font.h"
  38. #include "lists.h"
  39. #include "ir.h"
  40. #include "display.h"
  41. #include "io-abstract.h"
  42. #include "regions.h"
  43. #include "math.h"
  44. #include "input.h"
  45. #include "info.h"
  46.  
  47.  
  48. #if defined(HAVE_RINT)
  49. #ifdef __STDC__
  50. extern double rint (double);
  51. #else
  52. extern double rint ();
  53. #endif
  54. #else
  55. #define rint(x) (((x)<0) ? ceil((x)-.5) : floor((x)+.5))
  56. #endif
  57. static void record_damage ();
  58.  
  59. #ifdef __STDC__
  60. extern char * x_get_string_resource (XrmDatabase, char *, char *);
  61. extern XrmDatabase x_load_resources (Display *, char *, char *);
  62. extern char * getenv (const char *);
  63. #else
  64. extern char * x_get_string_resource ();
  65. extern XrmDatabase x_load_resources ();
  66. extern char * getenv ();
  67. #endif
  68.  
  69.  
  70. static char *emergency_font_name = "8x13";
  71. static char *cell_font_name = "times_roman12";
  72. static char *default_font_name = "8x13";
  73. static char *input_font_name = "8x13";
  74. static char *status_font_name = "6x10";
  75. static char *text_line_font_name = "8x13";
  76. static char *label_font_name = "5x8";
  77. int cell_font_point_size = 12;
  78. static char *default_bg_color_name = "black";
  79. static char *default_fg_color_name = "white";
  80.  
  81. /* If non-0 and !no_x, these display functions will be used. */
  82. char *io_x11_display_name = 0;
  83.  
  84. /* The geometry of the first window. */
  85. static int geom_x = 0;
  86. static int geom_y = 0;
  87. static int geom_w = 675;
  88. static int geom_h = 350;
  89. static char geom_string[] = "675x350+0+0";
  90.  
  91. /* This global is used only during command line and .Xdefaults handling. */
  92. static Display * theDisplay;
  93.  
  94. static char * rdb_class_name = "Oleo";
  95. static char * rdb_name = "oleo";
  96.  
  97. #if 0
  98. static XrmOptionDescRec x11_options[] =
  99. {
  100.   {0, 0, 0, 0}
  101. };
  102.  
  103. /* This dynamicly computes the size of x11_options to make 
  104.  * upkeep of this file less error prone.
  105.  */
  106. static int
  107.   count_options ()
  108. {
  109.   int x;
  110.   for (x = 0; x11_options[x].option; ++x)
  111.     ;
  112.   return x;
  113. }
  114. #endif
  115. /* This synthesizes class and generic names for resources (fancy strcat).
  116.  * Memory is reused after a reasonable number of calls. 
  117.  */
  118. #define RDB_NAME_BUF    8
  119. #define RDB_NAME_SIZE    256
  120.  
  121. #ifdef __STDC__
  122. static char * 
  123. resource_name (char * left, char * right)
  124. #else
  125. static char * 
  126. resource_name (left, right)
  127.      char * left;
  128.      char * right;
  129. #endif
  130. {
  131.   static char bufs[RDB_NAME_BUF][RDB_NAME_SIZE];
  132.   static int buf_pos = 0;
  133.   int len = strlen(left);
  134.   
  135.   bcopy (left, bufs[buf_pos], len);
  136.   bufs[buf_pos][len] = '.';
  137.   strcpy (bufs[buf_pos] + len + 1, right);
  138.   return bufs [buf_pos++];
  139. }
  140.  
  141. #ifdef __STDC__
  142. static char *
  143. class_of (char * foo)
  144. #else
  145. static char *
  146. class_of (foo)
  147.      char * foo;
  148. #endif
  149. {
  150.   return resource_name (rdb_class_name, foo);
  151. }
  152.  
  153. #ifdef __STDC__
  154. static char *
  155. name_of (char * foo)
  156. #else
  157. static char *
  158. name_of (foo)
  159.      char * foo;
  160. #endif
  161. {
  162.   return resource_name (rdb_name, foo);
  163. }
  164.  
  165. static XrmDatabase rdb;
  166.  
  167. #ifdef __STDC__
  168. void
  169. get_x11_args (int * argc_p, char ** argv)
  170. #else
  171. void
  172. get_x11_args (argc_p, argv)
  173.      int * argc_p;
  174.      char ** argv;
  175. #endif
  176. {
  177.   XrmInitialize ();
  178.   
  179. #if 0
  180.   XrmDatabase argv_resources;
  181.   /* Get the command line arguments. */
  182.   XrmParseCommand (&argv_resources, x11_options,
  183.            count_options (x11_options),
  184.            rdb_name, argc_p, argv);
  185.   
  186.   /* Compute the display from either resources or getenv. */
  187.   
  188.   io_x11_display_name =
  189.     x_get_string_resource (argv_resources, class_of ("Display"),
  190.                name_of ("display"));
  191. #endif                           
  192.   if (!io_x11_display_name)
  193.     io_x11_display_name = ck_savestr (getenv ("DISPLAY"));
  194.   
  195.   if (!io_x11_display_name)
  196.     return;
  197.   
  198.   theDisplay = XOpenDisplay (io_x11_display_name);
  199.   if (!theDisplay)
  200.     panic ("Can not connect to X.  Check your DISPLAY evironment variable.");
  201.   
  202.   FD_SET (ConnectionNumber (theDisplay), &read_fd_set);
  203.   FD_SET (ConnectionNumber (theDisplay), &exception_fd_set);
  204.   
  205.   /* Load the resource databases in a manner not unlike emacs :). */
  206.   rdb = x_load_resources (theDisplay, 0, rdb_class_name);
  207.   
  208. #if 0
  209.   /* Merge in the command line database.  */
  210.   XrmMergeDatabases (argv_resources, rdb);
  211. #endif
  212.   
  213.   /* Set up the various defaults (staticly declared above). */
  214.   {
  215.     char * val;
  216.     
  217.     val = x_get_string_resource (rdb, class_of ("Foreground"),
  218.                  name_of("foreground"));
  219.     if (val)
  220.       default_fg_color_name = val;
  221.     
  222.     val = x_get_string_resource (rdb, class_of ("Background"),
  223.                  name_of("background"));
  224.     if (val)
  225.       default_bg_color_name = val;
  226.     
  227.     val = x_get_string_resource (rdb, class_of ("Geometry"),
  228.                  name_of("geometry"));
  229.     if (val)
  230.       XGeometry (theDisplay, DefaultScreen(theDisplay), val, geom_string,
  231.          0, 1, 1, 0, 0, &geom_x, &geom_y, &geom_w, &geom_h);
  232.   }
  233. }
  234.  
  235.  
  236. static int x11_opened = 0;
  237. static struct sXport *thePort;
  238. typedef struct sXport *Xport;
  239.  
  240. struct sXport
  241. {
  242.   Display *dpy;
  243.   int screen;
  244.   Colormap color_map;
  245.   XColor fg_color;
  246.   XColor bg_color;
  247.   unsigned long fg_color_pixel;
  248.   unsigned long bg_color_pixel;
  249.   Window window;
  250.   Cursor mouse_cursor;
  251.   
  252.   XFontStruct *input_font;
  253.   XFontStruct *text_line_font;
  254.   XFontStruct *label_font;
  255.   XFontStruct *status_font;
  256.   
  257.   GC neutral_gc;
  258.   GC normal_gc;
  259.   GC standout_gc;
  260.   GC input_gc;
  261.   GC standout_input_gc;
  262.   GC text_line_gc;
  263.   GC text_line_standout_gc;
  264.   GC label_gc;
  265.   GC label_standout_gc;
  266.   GC status_gc;
  267.   
  268.   struct x_window *xwins;
  269.   int cursor_visible;        /* init to 1 */
  270.   int redisp_needed;
  271.   Atom wm_delete_window;
  272.   
  273.   /* The state of the input area. */
  274.   struct input_view input_view;
  275.  
  276.   /* If there is a message, that gets put in the input area. */
  277.   char * message;
  278.   int message_timeout;
  279. };
  280.  
  281. #ifdef __STDC__
  282. static void
  283. beep (Xport xport)
  284. #else
  285. static void
  286. beep (xport)
  287.      Xport xport;
  288. #endif
  289. {
  290. #if 0
  291.   XBell (xport->dpy, 30);
  292.   XFlush (xport->dpy);
  293. #endif
  294. }
  295.  
  296. #ifdef __STDC__
  297. static void
  298. xio_bell (void)
  299. #else
  300. static void
  301. xio_bell ()
  302. #endif
  303. {
  304.   beep (thePort);
  305. }
  306.  
  307.  
  308. #ifdef __STDC__
  309. static void
  310. draw_text_item (Xport xport, int c, int r, int wid, int hgt,
  311.         XFontStruct *font, GC gc, XTextItem *text, int do_clip)
  312. #else
  313. static void
  314. draw_text_item (xport, c, r, wid, hgt, font, gc, text, do_clip)
  315.      Xport xport;
  316.      int c;
  317.      int r;
  318.      int wid;
  319.      int hgt;
  320.      XFontStruct *font;
  321.      GC gc;
  322.      XTextItem *text;
  323.      int do_clip;
  324. #endif
  325. {
  326.   XRectangle clip;
  327.   int widused;
  328.   int tab_char;
  329.   XTextItem to_draw;
  330.  
  331.   clip.x = c;
  332.   clip.y = r;
  333.   clip.width = wid;
  334.   clip.height = hgt;
  335.   if (!x11_opened)
  336.     return;
  337.   if (do_clip)
  338.     XSetClipRectangles (xport->dpy, gc, 0, 0, &clip, 1, YXBanded);
  339.  
  340.  
  341.   tab_char = 0;
  342.   to_draw = *text;
  343.   widused = 0;
  344.   while (to_draw.nchars)
  345.     {
  346.       XTextItem draw_now;
  347.       XTextItem after_tab;
  348.  
  349.       /* Draw tab characters carefully. */
  350.       {
  351.     int x;
  352.     for (x = 0; x < to_draw.nchars; ++x)
  353.       if (to_draw.chars[x] == '\t')
  354.         {
  355.           draw_now = to_draw;
  356.           draw_now.nchars = x;
  357.           after_tab = to_draw;
  358.           after_tab.chars += x + 1;
  359.           after_tab.nchars -= x + 1;
  360.           goto draw_burst;
  361.         }
  362.     /* No tabs found. */
  363.     draw_now = to_draw;
  364.     bzero (&after_tab, sizeof (after_tab));
  365.       }
  366.  
  367.     draw_burst:
  368.       XDrawImageString (xport->dpy, xport->window, gc,
  369.             c + widused, r + font->ascent,
  370.             draw_now.chars, draw_now.nchars);
  371.       widused += XTextWidth (font, draw_now.chars, draw_now.nchars);
  372.       tab_char += draw_now.nchars;
  373.       if (after_tab.chars)
  374.     {
  375.       int tab_stop_col = ((tab_char + 8 - tab_char % 8)
  376.                   * font->max_bounds.width);
  377.       XFillRectangle (xport->dpy, xport->window, xport->neutral_gc,
  378.               c + widused, r, tab_stop_col - widused, hgt);
  379.       widused = tab_stop_col;
  380.       tab_char += 8 - tab_char % 8;
  381.     }
  382.       to_draw = after_tab;
  383.     }
  384.  
  385.   if (widused < wid)
  386.     XFillRectangle (xport->dpy, xport->window, xport->neutral_gc,
  387.             c + widused, r, wid - widused, hgt);
  388.   if (do_clip)
  389.     XSetClipMask (xport->dpy, gc, None);
  390. }
  391.  
  392. #ifdef __STDC__
  393. static void
  394. xio_redraw_input_cursor (int on)
  395. #else
  396. static void
  397. xio_redraw_input_cursor (on)
  398.      int on;
  399. #endif
  400. {
  401.   struct input_view * iv = &thePort->input_view;
  402.   int offset = iv->input_cursor - iv->visibility_begin;
  403.   int start;
  404.   XTextItem cursor_text;
  405.   int cwid;
  406.   int ypos = (iv->current_info ? 0 : input);
  407.   char * inp;
  408.  
  409.   inp = (iv->input_area
  410.      ? iv->input_area->buf + iv->visibility_begin
  411.      : "");
  412.   start = (XTextWidth (thePort->input_font, inp, offset) + iv->prompt_wid);
  413.  
  414.   cursor_text.font = thePort->input_font->fid;
  415.   cursor_text.nchars = 1;
  416.   if (iv->input_cursor <= iv->visibility_end)
  417.     {
  418.       cwid = XTextWidth (thePort->input_font, inp + offset, 1);
  419.       cursor_text.chars = inp + offset;
  420.     }
  421.   else
  422.     {
  423.       cwid = XTextWidth (thePort->input_font, " ", 1);
  424.       cursor_text.chars = " ";
  425.     }
  426.   draw_text_item (thePort, start, ypos, cwid, input_rows,
  427.           thePort->input_font,
  428.           (on ? thePort->standout_input_gc : thePort->input_gc),
  429.           &cursor_text, 1);
  430. }
  431.  
  432. #ifdef __STDC__
  433. static void
  434. xio_cellize_cursor (void)
  435. #else
  436. static void
  437. xio_cellize_cursor ()
  438. #endif
  439. {
  440.   xio_redraw_input_cursor (0);
  441. }
  442.  
  443. #ifdef __STDC__
  444. static void
  445. xio_inputize_cursor (void)
  446. #else
  447. static void
  448. xio_inputize_cursor ()
  449. #endif
  450. {
  451.   xio_redraw_input_cursor (1);
  452. }
  453.  
  454. static int
  455. x_input_metric (str, len)
  456.      char * str;
  457.      int len;
  458. {
  459.   return XTextWidth (thePort->input_font, str, len);
  460. }
  461.  
  462. /* This redraws the input area without recomputing anything. */
  463. #ifdef __STDC__
  464. static void
  465. xio_redraw_input (void)
  466. #else
  467. static void
  468. xio_redraw_input ()
  469. #endif
  470. {
  471.   if (thePort->message)
  472.     {                /* This isn't in use. */
  473.       XTextItem text;
  474.       text.chars = thePort->message;
  475.       text.nchars = strlen (thePort->message);
  476.       text.font = thePort->input_font->fid;
  477.       draw_text_item (thePort, 0, input, scr_cols, input_rows,
  478.               thePort->input_font, thePort->input_gc,
  479.               &text, 1);
  480.       return;
  481.     }
  482.  
  483.   {
  484.     struct input_view * iv = &thePort->input_view;
  485.     int ypos = (iv->current_info ? 0 : input);
  486.  
  487.     if (iv->redraw_needed == NO_REDRAW)
  488.       return;
  489.     if (iv->redraw_needed == FULL_REDRAW)
  490.       {
  491.     XTextItem text;
  492.     if (iv->expanded_keymap_prompt)
  493.       {
  494.         text.font = thePort->input_font->fid;
  495.         text.chars = iv->expanded_keymap_prompt;
  496.         text.nchars = strlen (iv->expanded_keymap_prompt);
  497.         draw_text_item (thePort,
  498.                 0, ypos, scr_cols, input_rows,
  499.                 thePort->input_font, thePort->input_gc,
  500.                 &text, 0);
  501.         iv->redraw_needed = NO_REDRAW;
  502.         if (input_active || iv->current_info)
  503.           xio_redraw_input_cursor (1);
  504.         return;
  505.       }
  506.     else if (iv->prompt_wid)
  507.       {
  508.         text.font = thePort->input_font->fid;
  509.         text.chars = iv->prompt;
  510.         text.nchars = prompt_len (text.chars);
  511.         draw_text_item (thePort, 0, ypos, iv->prompt_wid, input_rows,
  512.                 thePort->input_font, thePort->input_gc,
  513.                 &text, 0);
  514.       }
  515.       }
  516.     
  517.     if (!iv->input_area
  518.     || (iv->visibility_begin > iv->visibility_end))
  519.       {
  520.     XFillRectangle (thePort->dpy, thePort->window, thePort->neutral_gc,
  521.             iv->prompt_wid, ypos,
  522.             scr_cols - iv->prompt_wid, input_rows);
  523.     iv->redraw_needed = NO_REDRAW;
  524.     return;
  525.       }
  526.     
  527.     
  528.     if (iv->visibility_end >= iv->visibility_begin)
  529.       {
  530.     int pos = ((iv->redraw_needed == FULL_REDRAW)
  531.            ? iv->visibility_begin
  532.            : iv->redraw_needed);
  533.  
  534.     int xpos = (iv->prompt_wid
  535.             + XTextWidth (thePort->input_font,
  536.                   iv->input_area->buf + iv->visibility_begin,
  537.                   pos - iv->visibility_begin));
  538.     int wid = scr_cols - xpos;
  539.     int hgt = input_rows;
  540.  
  541.     XTextItem text;
  542.  
  543.     text.font = thePort->input_font->fid;
  544.     text.chars = iv->input_area->buf + pos;
  545.     text.nchars = iv->visibility_end - pos + 1;
  546.  
  547.     draw_text_item (thePort, xpos, ypos, wid, hgt, 
  548.             thePort->input_font, thePort->input_gc,
  549.             &text, 0);
  550.  
  551.     if (input_active || iv->current_info)
  552.       xio_redraw_input_cursor (1);
  553.     iv->redraw_needed = NO_REDRAW;
  554.       }
  555.   }
  556. }
  557.  
  558.  
  559. #ifdef __STDC__
  560. static void
  561. xio_fix_input (void)
  562. #else
  563. static void
  564. xio_fix_input ()
  565. #endif
  566. {
  567.   iv_fix_input (&thePort->input_view);
  568. }
  569.  
  570. #ifdef __STDC__
  571. static void
  572. xio_move_cursor (void)
  573. #else
  574. static void
  575. xio_move_cursor ()
  576. #endif
  577. {
  578.   if (input_active)
  579.     xio_redraw_input_cursor (0);
  580.   iv_move_cursor (&thePort->input_view);
  581.   if (input_active)
  582.     xio_redraw_input_cursor (1);
  583. }
  584.  
  585. #ifdef __STDC__
  586. static void
  587. xio_erase (int len)
  588. #else
  589. static void
  590. xio_erase (len)
  591.      int len;
  592. #endif
  593. {
  594.   iv_erase (&thePort->input_view, len);
  595. }
  596.  
  597. #ifdef __STDC__
  598. static void
  599. xio_insert (int len)
  600. #else
  601. static void
  602. xio_insert (len)
  603.      int len;
  604. #endif
  605. {
  606.   iv_insert (&thePort->input_view, len);
  607. }
  608.        
  609. #ifdef __STDC__
  610. static void
  611. xio_over (char * str, int len)
  612. #else
  613. static void
  614. xio_over (str, len)
  615.      char * str;
  616.      int len;
  617. #endif
  618. {
  619.   iv_over (&thePort->input_view, len);
  620. }
  621.  
  622. #ifdef __STDC__
  623. int
  624. io_col_to_input_pos (int c)
  625. #else
  626. int
  627. io_col_to_input_pos (c)
  628.      int c;
  629. #endif
  630. {
  631.   struct input_view * iv = &thePort->input_view;
  632.   char * prompt = (iv->expanded_keymap_prompt
  633.            ? iv->expanded_keymap_prompt
  634.            : (iv->prompt ? iv->prompt : ""));
  635.   int prompt_wid = iv->prompt_metric (prompt, strlen(prompt));
  636.  
  637.   c -= prompt_wid;
  638.   {
  639.     int cpos;
  640.     int max = iv->visibility_end - iv->visibility_begin + 1;
  641.     for (cpos = 1; cpos < max; ++cpos)
  642.       if (iv->input_metric (iv->input_area->buf + iv->visibility_begin, cpos)
  643.       >= c)
  644.     break;
  645.     return iv->visibility_begin + cpos - 1;
  646.   }
  647. }
  648.  
  649.  
  650. /****************************************************************
  651.  * Low level Input
  652.  ****************************************************************/
  653.  
  654. /* To be like curses, we offer this option: */
  655. static int block_on_getch = 1;
  656.  
  657. /* This is the buffer of decoded keyboard events. */
  658. static char *input_buf = 0;
  659. static int input_buf_allocated = 0;
  660. static int chars_buffered = 0;
  661. #define MAX_KEY_TRANSLATION    (1024)
  662.  
  663. static XComposeStatus compose;
  664.  
  665. #ifdef __STDC__
  666. static void
  667. xio_scan_for_input (int blockp)
  668. #else
  669. static void
  670. xio_scan_for_input (blockp)
  671.      int blockp;
  672. #endif
  673. {
  674.   XEvent event_return;
  675.   static int pendingw;
  676.   static int pendingh;
  677.   static int resize_pending = 0;
  678.   int events_pending;
  679.   int len;
  680.   
  681.   events_pending = XPending (thePort->dpy);
  682.   do
  683.     {
  684.       if (resize_pending && !events_pending)
  685.     {
  686.       if (   ((pendingh / height_scale) > 9.)
  687.           && ((pendingw / width_scale) > 9.))
  688.           {
  689.         io_set_scr_size (pendingh, pendingw);
  690.         resize_pending = 0;
  691.           }
  692.     }
  693.       
  694.       if (!events_pending)
  695.     io_redisp ();
  696.       
  697.       if (events_pending || blockp)
  698.     XNextEvent (thePort->dpy, &event_return);
  699.       else
  700.     return;
  701.       
  702.       switch (event_return.type)
  703.     {
  704.     case ClientMessage:
  705.       if (event_return.xclient.data.l[0] == thePort->wm_delete_window)
  706.         {
  707.           XCloseDisplay(thePort->dpy);
  708.           exit(0);
  709.         }
  710.       break;
  711.     case KeyPress:
  712.     case ButtonPress:
  713.     case ButtonRelease:
  714.       if (chars_buffered + MAX_KEY_TRANSLATION >= input_buf_allocated)
  715.         {
  716.           input_buf_allocated =
  717.         2 * (input_buf_allocated
  718.              ? input_buf_allocated
  719.              : MAX_KEY_TRANSLATION);
  720.           input_buf =
  721.         (char *) ck_remalloc (input_buf, input_buf_allocated);
  722.         }
  723.     }
  724.       
  725.       
  726.       switch (event_return.type)
  727.     {
  728.     case KeyPress:
  729.       len = XLookupString (&event_return,
  730.                    input_buf + chars_buffered,
  731.                    MAX_KEY_TRANSLATION, 0, &compose);
  732.       if ((len == 1) && (event_return.xkey.state & Mod1Mask))
  733.         input_buf[chars_buffered] |= 0x80;
  734.       chars_buffered += len;
  735.       break;
  736.       
  737.     case ButtonPress:
  738.     case ButtonRelease:
  739.       {
  740.         int seq =
  741.           enqueue_mouse_event (event_return.xbutton.y,
  742.                    event_return.xbutton.x,
  743.                    event_return.xbutton.button,
  744.                    event_return.type == ButtonPress);
  745.         input_buf[chars_buffered++] = MOUSE_CHAR;
  746.         input_buf[chars_buffered++] =
  747.           event_return.xbutton.button - 1 + '0';
  748.         input_buf[chars_buffered++] = (char) seq;
  749.         break;
  750.       }
  751.       
  752.     case Expose:
  753.       record_damage (thePort,
  754.              event_return.xexpose.x, event_return.xexpose.y,
  755.              event_return.xexpose.width,
  756.              event_return.xexpose.height);
  757.       break;
  758.       
  759.     case MapNotify:
  760.       break;
  761.       
  762.     case ReparentNotify:
  763.       break;
  764.       
  765.     case ConfigureNotify:
  766.       pendingw = event_return.xconfigure.width;
  767.       pendingh = event_return.xconfigure.height;
  768.       resize_pending = 1;
  769.       break;
  770.       
  771.     default:
  772.       break;
  773.     }
  774.       events_pending = XPending (thePort->dpy);
  775.     }
  776.   while (events_pending || !chars_buffered);
  777. }
  778.  
  779.  
  780. #ifdef __STDC__
  781. static int
  782. xio_input_avail (void)
  783. #else
  784. static int
  785. xio_input_avail ()
  786. #endif
  787. {
  788.   return chars_buffered;
  789. }
  790.  
  791. #ifdef __STDC__
  792. static void
  793. xio_wait_for_input (void)
  794. #else
  795. static void
  796. xio_wait_for_input ()
  797. #endif
  798. {
  799.   io_scan_for_input (1);
  800. }
  801.  
  802. #ifdef __STDC__
  803. static int
  804. xio_read_kbd (VOLATILE char *buffer, int size)
  805. #else
  806. static int
  807. xio_read_kbd (buffer, size)
  808.      VOLATILE char *buffer;
  809.      int size;
  810. #endif
  811. {
  812.   int amt_read = size < chars_buffered ? size : chars_buffered;
  813.   bcopy (input_buf, (char *) buffer, amt_read);
  814.   chars_buffered -= amt_read;
  815.   if (chars_buffered)
  816.     bcopy ((char *) input_buf + amt_read, (char *) input_buf, chars_buffered);
  817.   return amt_read;
  818. }
  819.  
  820. #ifdef __STDC__
  821. static void
  822. xio_nodelay (int delayp)
  823. #else
  824. static void
  825. xio_nodelay (delayp)
  826.      int delayp;
  827. #endif
  828. {
  829.   block_on_getch = delayp;
  830. }
  831.  
  832. #ifdef __STDC__
  833. static int
  834. xio_getch (void)
  835. #else
  836. static int
  837. xio_getch ()
  838. #endif
  839. {
  840.   char buf;
  841.   
  842.   if (!chars_buffered)
  843.     io_scan_for_input (block_on_getch);
  844.   
  845.   if (chars_buffered)
  846.     {
  847.       io_read_kbd (&buf, 1);
  848.       return buf;
  849.     }
  850.   else
  851.     return 0;
  852. }
  853.  
  854.  
  855. /****************************************************************
  856.  * Low level support for input and status areas.
  857.  ****************************************************************/
  858.  
  859. /*
  860.  * CRAM tells how many characters of a string will fit within
  861.  * a given number of cols, presuming that if they don't all fit,
  862.  * the string CONTINUE must be added to the end of those that do.
  863.  */
  864. #ifdef __STDC__
  865. static int
  866. cram (int cols, XFontStruct *font, char *text, int len, char *continuation)
  867. #else
  868. static int
  869. cram (cols, font, text, len, continuation)
  870.      int cols;
  871.      XFontStruct *font;
  872.      char *text;
  873.      int len;
  874.      char *continuation;
  875. #endif
  876. {
  877.   int cont_cols = XTextWidth (font, continuation, strlen (continuation));
  878.   int cols_used = 0;
  879.   int x = 0;
  880.   
  881.   if (XTextWidth (font, text, len) < cols)
  882.     return len;
  883.   
  884.   cols_used = 0;
  885.   while (x < len && cols_used < (cols - cont_cols))
  886.     cols_used += XTextWidth (font, text + x, 1);
  887.   
  888.   return x;
  889. }
  890.  
  891.  
  892.  
  893.  
  894. #ifdef __STDC__
  895. static void
  896. set_text (XTextItem *xtext, char *text, int len)
  897. #else
  898. static void
  899. set_text (xtext, text, len)
  900.      XTextItem *xtext;
  901.      char *text;
  902.      int len;
  903. #endif
  904. {
  905.   if (xtext->nchars < len)
  906.     {
  907.       xtext->chars = ck_remalloc (xtext->chars, len);
  908.       xtext->nchars = len;
  909.     }
  910.   bcopy (text, xtext->chars, len);
  911.   while (len < xtext->nchars)
  912.     xtext->chars[len++] = ' ';
  913. }
  914.  
  915.  
  916.  
  917. /* The input area. */
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924. /*
  925.  * Low level interface to the input area specificly.
  926.  */
  927.  
  928. static XTextItem input_text;
  929. static int term_cursor_visible = 0;
  930. static int input_cursor = 0;    /* Position of cursor, if visible */
  931. static int textout;
  932. static int input_more_mode = 0;
  933.  
  934. #ifdef __STDC__
  935. static void
  936. draw_input (void)
  937. #else
  938. static void
  939. draw_input ()
  940. #endif
  941. {
  942.   if (!input_text.chars)
  943.     {
  944.       XFillRectangle (thePort->dpy, thePort->window, thePort->neutral_gc,
  945.               input, 0, scr_cols, input_rows);
  946.       return;
  947.     }
  948.   input_text.font = thePort->input_font->fid;
  949.   draw_text_item (thePort, 0, input, scr_cols, input_rows, thePort->input_font,
  950.           thePort->input_gc, &input_text, 1);
  951.   if (input_more_mode)
  952.     {
  953.       XTextItem more_text;
  954.       int mwid = XTextWidth (thePort->input_font, "[more]", 6);
  955.       more_text.chars = "[MORE]";
  956.       more_text.nchars = 6;
  957.       more_text.delta = 0;
  958.       more_text.font = thePort->input_font->fid;
  959.       draw_text_item (thePort, scr_cols - mwid, input, mwid, input_rows,
  960.               thePort->input_font, thePort->standout_input_gc,
  961.               &more_text, 1);
  962.     }
  963.   else if (term_cursor_visible)
  964.     {
  965.       int start = XTextWidth (thePort->input_font, input_text.chars, input_cursor);
  966.       int cwid = XTextWidth (thePort->input_font,
  967.                  input_text.chars + input_cursor, 1);
  968.       XTextItem cursor_text;
  969.       cursor_text.chars = input_text.chars + input_cursor;
  970.       cursor_text.nchars = 1;
  971.       cursor_text.font = thePort->input_font->fid;
  972.       draw_text_item (thePort, start, input, cwid, input_rows,
  973.               thePort->input_font, thePort->standout_input_gc,
  974.               &cursor_text, 1);
  975.     }
  976. }
  977.  
  978.  
  979. #ifdef __STDC__
  980. static void
  981. xio_clear_input_before (void)
  982. #else
  983. static void
  984. xio_clear_input_before ()
  985. #endif
  986. {
  987.   textout = 0;
  988.   if (topclear == 2)
  989.     {
  990.       int x;
  991.       for (x = 0; x < input_text.nchars; ++x)
  992.     input_text.chars[x] = ' ';
  993.       input_cursor = 0;
  994.       draw_input ();
  995.       topclear = 0;
  996.     }
  997. }
  998.  
  999. #ifdef __STDC__
  1000. static void
  1001. xio_clear_input_after (void)
  1002. #else
  1003. static void
  1004. xio_clear_input_after ()
  1005. #endif
  1006. {
  1007.   if (topclear)
  1008.     {
  1009.       int x;
  1010.       for (x = 0; x < input_text.nchars; ++x)
  1011.     input_text.chars[x] = ' ';
  1012.       input_cursor = 0;
  1013.       draw_input ();
  1014.       topclear = 0;
  1015.     }
  1016. }
  1017.  
  1018. #ifdef __STDC__
  1019. static void
  1020. set_input (char *text, int len, int cursor)
  1021. #else
  1022. static void
  1023. set_input (text, len, cursor)
  1024.      char *text;
  1025.      int len;
  1026.      int cursor;
  1027. #endif
  1028. {
  1029.   set_text (&input_text, text, len);
  1030.   if (cursor + 1 > input_text.nchars)
  1031.     {
  1032.       input_text.chars = (char *) ck_remalloc (input_text.chars, cursor + 1);
  1033.       while (input_text.nchars < cursor + 1)
  1034.     input_text.chars[input_text.nchars++] = ' ';
  1035.     }
  1036.   input_cursor = cursor;
  1037.   draw_input ();
  1038. }
  1039.  
  1040.  
  1041. /*
  1042.  * Low level interface to the status area specificly.
  1043.  */
  1044. static XTextItem status_text;
  1045.  
  1046. #ifdef __STDC__
  1047. static void
  1048. draw_status (void)
  1049. #else
  1050. static void
  1051. draw_status ()
  1052. #endif
  1053. {
  1054.   if (!x11_opened || thePort->input_view.current_info)
  1055.     return;
  1056.   if (user_status)
  1057.     draw_text_item (thePort, 0, status, scr_cols,
  1058.             status_rows, thePort->status_font,
  1059.             thePort->status_gc, &status_text, 1);
  1060. }
  1061.  
  1062. #ifdef __STDC__
  1063. static void
  1064. set_status (char *text)
  1065. #else
  1066. static void
  1067. set_status (text)
  1068.      char *text;
  1069. #endif
  1070. {
  1071.   set_text (&status_text, text, strlen (text));
  1072.   status_text.font = thePort->status_font->fid;
  1073.   draw_status ();
  1074. }
  1075.  
  1076.  
  1077. /****************************************************************
  1078.  * High level interfaces for the input and status areas.
  1079.  ****************************************************************/
  1080.  
  1081. #ifdef __STDC__
  1082. static void
  1083. xio_update_status (void)
  1084. #else
  1085. static void
  1086. xio_update_status ()
  1087. #endif
  1088. {
  1089.   CELL *cp;
  1090.   char *dec;
  1091.   char *ptr;
  1092.   int plen;
  1093.   int dlen;
  1094.   int mplen;
  1095.   char buf[1024];
  1096.   char *assembled;
  1097.   char *pos = buf;
  1098.   
  1099.   if (!user_status)
  1100.     return;
  1101.   
  1102.   if (mkrow != NON_ROW)
  1103.     {
  1104.       struct rng r;
  1105.       *pos++ = '*';
  1106.       set_rng (&r, curow, cucol, mkrow, mkcol);
  1107.       ptr = range_name (&r);
  1108.     }
  1109.   else
  1110.     ptr = cell_name (curow, cucol);
  1111.   bcopy (ptr, pos, strlen (ptr));
  1112.   pos += strlen (ptr);
  1113.   if (how_many != 1)
  1114.     {
  1115.       sprintf (pos, " {%d}", how_many);
  1116.       pos += strlen (pos);
  1117.     }
  1118.   *pos++ = ' ';
  1119.   mplen = XTextWidth (thePort->status_font, buf, pos - buf);
  1120.   
  1121.   if ((cp = find_cell (curow, cucol)) && cp->cell_formula)
  1122.     {
  1123.       dec = decomp (curow, cucol, cp);
  1124.       dlen = XTextWidth (thePort->status_font, dec, strlen (dec));
  1125.     }
  1126.   else
  1127.     {
  1128.       dec = 0;
  1129.       dlen = 0;
  1130.     }
  1131.   
  1132.   ptr = cell_value_string (curow, cucol);
  1133.   plen = XTextWidth (thePort->status_font, ptr, strlen (ptr));
  1134.   
  1135.   assembled = (char *) ck_malloc (plen + dlen + mplen);
  1136.   bcopy (buf, assembled, pos - buf);
  1137.   pos = assembled + (pos - buf);
  1138.   
  1139.   {
  1140.     int c;
  1141.     int l;
  1142.     int wid;
  1143.     
  1144.     l = strlen (ptr);
  1145.     c = cram (scr_cols - mplen - thePort->status_font->max_bounds.width,
  1146.           thePort->status_font, ptr, l, (dec ? " [...]" : "..."));
  1147.     bcopy (ptr, pos, c);
  1148.     pos += c;
  1149.     if (c == l)
  1150.       *pos++ = ' ';
  1151.     else if (dec)
  1152.       {
  1153.     bcopy (" [...]", pos, 6);
  1154.     pos += 6;
  1155.     dec = 0;
  1156.     dlen = 0;
  1157.     decomp_free ();
  1158.       }
  1159.     else
  1160.       {
  1161.     bcopy ("...", pos, 3);
  1162.     pos += 3;
  1163.       }
  1164.     *pos++ = ' ';
  1165.     wid = XTextWidth (thePort->status_font, assembled, pos - assembled);
  1166.     
  1167.     if (dec)
  1168.       {
  1169.     l = strlen (dec);
  1170.     c = cram (scr_cols - wid, thePort->status_font, dec, l, "[...]");
  1171.     *pos++ = '[';
  1172.     if (c < l)
  1173.       {
  1174.         bcopy (dec, pos, c);
  1175.         bcopy ("...]", pos, 4);
  1176.         pos += c + 4;
  1177.       }
  1178.     else
  1179.       {
  1180.         bcopy (dec, pos, c);
  1181.         pos += c;
  1182.         *pos++ = ']';
  1183.       }
  1184.       }
  1185.     
  1186.     *pos++ = '\0';
  1187.     set_status (assembled);
  1188.     draw_status ();
  1189.     free (assembled);
  1190.   }
  1191. }
  1192.  
  1193.  
  1194. #ifdef __STDC__
  1195. static int
  1196. xio_get_chr (char *prompt)
  1197. #else
  1198. static int
  1199. xio_get_chr (prompt)
  1200.      char *prompt;
  1201. #endif
  1202. {
  1203.   int len = strlen (prompt);
  1204.   set_input (prompt, len, len);
  1205.   topclear = 2;
  1206.   draw_input ();
  1207.   return io_getch ();
  1208. }
  1209.  
  1210.  
  1211. /*
  1212.  * Multi-line informational messages to the user:
  1213.  */
  1214.  
  1215. /* old: */
  1216. struct text_line
  1217. {
  1218.   struct text_line *next;
  1219.   int nchars;
  1220.   int standout;
  1221.   char line[TAIL_ARRAY];
  1222. };
  1223. static int text_damaged = 0;
  1224. static struct text_line *text_lines = 0;
  1225. extern int auto_recalc;
  1226.  
  1227.  
  1228. /****************************************************************
  1229.  * Low level support for the cell windows.
  1230.  ****************************************************************/
  1231.  
  1232. /* Every cell has an associated font name.  This is a cache mapping
  1233.  * font names and scales to graphics contexts.
  1234.  */
  1235.  
  1236. struct cell_gc
  1237. {
  1238.   struct cell_gc *next;
  1239.   struct cell_gc *prev;
  1240.   Xport port;
  1241.   GC gc;
  1242.   char *font_name;
  1243.   double scale;
  1244.   XFontStruct *font;
  1245.   int clipped_to;
  1246.   int cursor:1;
  1247. };
  1248.  
  1249. /* The cell_gc cache is only valid for a specific size default font.  If the
  1250.  * defualt font size changes, then the cache must be flushed.
  1251.  */
  1252. static int cell_gc_basis = 12;
  1253.  
  1254.  
  1255. /* Individual cache entries are also validated by the clipping set for their
  1256.  * gc.  To the rest of the system, it appears that there is one clipping region
  1257.  * for all cell_gc's.
  1258.  */
  1259. static int clipcnt = 0;
  1260. static int cliprectc = 0;
  1261. static int cliprect_alloc = 0;
  1262. static XRectangle *cliprectv = 0;
  1263.  
  1264. #define GC_CACHE_SIZE    10
  1265. static struct cell_gc *cell_gc_cache = 0;
  1266.  
  1267.  
  1268. /* This takes the full name of an X11 font, and returns its point size (in
  1269.  * tenths of a point.  If the string is not a valid font name, 0 is returned.
  1270.  */
  1271.  
  1272. #ifdef __STDC__
  1273. static int 
  1274. name_to_ps (char *xfont)
  1275. #else
  1276. static int 
  1277. name_to_ps (xfont)
  1278.      char *xfont;
  1279. #endif
  1280. {
  1281.   while (*xfont)
  1282.     if (*xfont == '-')
  1283.       {
  1284.     ++xfont;
  1285.     if (*xfont == '-')    /* look for -- */
  1286.       {
  1287.         ++xfont;
  1288.         break;
  1289.       }
  1290.       }
  1291.     else
  1292.       ++xfont;
  1293.   if (!*xfont)
  1294.     return 0;
  1295.   while (isdigit (*xfont++));
  1296.   --xfont;
  1297.   if (!*xfont++ == '-')
  1298.     return 0;
  1299.   return atoi (xfont);
  1300. }
  1301.  
  1302.  
  1303. #define ABS(A) ((A) < 0 ? -(A) : (A))
  1304.  
  1305. #ifdef __STDC__
  1306. static struct cell_gc *
  1307. cell_gc (Xport port, struct font_memo *font_passed, int cursor)
  1308. #else
  1309. static struct cell_gc *
  1310. cell_gc (port, font_passed, cursor)
  1311.      Xport port;
  1312.      struct font_memo *font_passed;
  1313.      int cursor;
  1314. #endif
  1315. {
  1316.   struct font_memo *font =
  1317.     (font_passed ? font_passed : default_font());
  1318.   char *font_name = font->names->x_name;
  1319.   double scale = font->scale;
  1320.   struct cell_gc *c = cell_gc_cache;
  1321.   if (cell_gc_basis != cell_font_point_size)
  1322.     {
  1323.       do
  1324.     {
  1325.       if (c->font_name)
  1326.         {
  1327.           XFreeFont (c->port->dpy, c->font);
  1328.           free (c->font_name);
  1329.         }
  1330.       c->font_name = 0;
  1331.       c->port = 0;
  1332.       c->font = 0;
  1333.       c = c->next;
  1334.     }
  1335.       while (c != cell_gc_cache);
  1336.       cell_gc_basis = cell_font_point_size;
  1337.     }
  1338.   else
  1339.     {
  1340.       do
  1341.     {
  1342.       if ((c->scale == scale)
  1343.           && port == c->port
  1344.           && c->font_name && !strcmp (font_name, c->font_name))
  1345.         {
  1346.           if (cell_gc_cache == c)
  1347.         cell_gc_cache = cell_gc_cache->next;
  1348.           c->next->prev = c->prev;
  1349.           c->prev->next = c->next;
  1350.           c->next = cell_gc_cache;
  1351.           c->prev = cell_gc_cache->prev;
  1352.           c->prev->next = c;
  1353.           c->next->prev = c;
  1354.           cell_gc_cache = c;
  1355.           goto check_clipping;
  1356.         }
  1357.       c = c->next;
  1358.     }
  1359.       while (c != cell_gc_cache);
  1360.     }
  1361.   
  1362.   c = c->prev;
  1363.   cell_gc_cache = c;
  1364.   if (c->font_name)
  1365.     {
  1366.       XFreeFont (c->port->dpy, c->font);
  1367.       free (c->font_name);
  1368.     }
  1369.   c->port = port;
  1370.   c->scale = scale;
  1371.   {
  1372.     char **fontv;
  1373.     int fontc;
  1374.     fontv = XListFonts (port->dpy, font_name, 1024, &fontc);
  1375.     if (fontv)
  1376.       {
  1377.     int x, best;
  1378.     int ideal_size = rint (scale * (double) cell_font_point_size * 10.);
  1379.     int best_dist;
  1380.     best = 0;
  1381.     best_dist = ideal_size - name_to_ps (fontv[0]);
  1382.     for (x = 1; x < fontc; ++x)
  1383.       {
  1384.         int ps = name_to_ps (fontv[x]);
  1385.         int tdist = ideal_size - ps;
  1386.         if (ABS (tdist) < ABS (best_dist)
  1387.         || ((ABS (tdist) == ABS (best_dist)) && (tdist > best_dist)))
  1388.           {
  1389.         best_dist = tdist;
  1390.         best = x;
  1391.           }
  1392.       }
  1393.     c->font = XLoadQueryFont (port->dpy, fontv[best]);
  1394.     XFreeFontNames (fontv);
  1395.       }
  1396.     else
  1397.       c->font = 0;
  1398.   }
  1399.   if (c->font)
  1400.     c->font_name = (char *) ck_savestr (font_name);
  1401.   else
  1402.     {
  1403.       c->font = XLoadQueryFont (port->dpy, cell_font_name);
  1404.       if (c->font)
  1405.     c->font_name = ck_savestr (cell_font_name);
  1406.       else
  1407.     {
  1408.       c->font = XLoadQueryFont (port->dpy, emergency_font_name);
  1409.       if (c->font)
  1410.         c->font_name = ck_savestr (emergency_font_name);
  1411.       else
  1412.         panic ("Unable to load even the emergency font.");
  1413.     }
  1414.     }
  1415.   
  1416.   {
  1417.     XGCValues v;
  1418.     v.font = c->font->fid;
  1419.     XChangeGC (port->dpy, c->gc, GCFont, &v);
  1420.   }
  1421.   
  1422.  check_clipping:
  1423.   
  1424.   if (clipcnt != c->clipped_to)
  1425.     {
  1426.       XSetClipRectangles (port->dpy, c->gc, 0, 0, cliprectv, cliprectc, Unsorted);
  1427.       c->clipped_to = clipcnt;
  1428.     }
  1429.   
  1430.   {
  1431.     XGCValues v;
  1432.     v.foreground = cursor ? port->bg_color_pixel : port->fg_color_pixel;
  1433.     v.background = cursor ? port->fg_color_pixel : port->bg_color_pixel;
  1434.     XChangeGC (port->dpy, c->gc, GCForeground | GCBackground, &v);
  1435.     c->cursor = cursor;
  1436.   }
  1437.   return c;
  1438. }
  1439.  
  1440.  
  1441.  
  1442. /* This is the data for an oleo window, displayed under X. */
  1443.  
  1444. enum kinds_of_layout_needed
  1445. {
  1446.   damaged_display = 1,
  1447.   new_display = 2
  1448. };
  1449.  
  1450. struct x_window
  1451. {
  1452.   struct x_window *next;
  1453.   struct window *win;
  1454.   struct display display;
  1455.   int layout_needed;
  1456.   int label_damage;
  1457.   Xport port;
  1458. };
  1459.  
  1460.  
  1461.  
  1462. #ifdef __STDC__
  1463. static void
  1464. collect_clipping (xx_IntRectangle rect)
  1465. #else
  1466. static void
  1467. collect_clipping (rect)
  1468.      xx_IntRectangle rect;
  1469. #endif
  1470. {
  1471.   if (cliprectc == cliprect_alloc)
  1472.     {
  1473.       cliprect_alloc = cliprect_alloc ? cliprect_alloc * 2 : 16;
  1474.       cliprectv =
  1475.     ((XRectangle *)
  1476.      ck_remalloc (cliprectv,
  1477.               cliprect_alloc * sizeof (XRectangle)));
  1478.     }
  1479.   cliprectv[cliprectc].x = rect->x;
  1480.   cliprectv[cliprectc].y = rect->y;
  1481.   cliprectv[cliprectc].width = rect->w;
  1482.   cliprectv[cliprectc].height = rect->h;
  1483.   ++cliprectc;
  1484. }
  1485.  
  1486. #ifdef __STDC__
  1487. static void 
  1488. clip_to_intrectangle (struct x_window * xwin, xx_IntRectangle rect)
  1489. #else
  1490. static void 
  1491. clip_to_intrectangle (xwin, rect)
  1492.      struct x_window * xwin;
  1493.      xx_IntRectangle rect;
  1494. #endif
  1495. {
  1496.   struct window * win = xwin->win;
  1497.   int x_ceil = win->win_over + win->numc;
  1498.   int y_ceil = win->win_down + win->numr;
  1499.  
  1500.   if (rect->w + rect->x >= x_ceil)
  1501.     {
  1502.       rect->w = x_ceil - rect->x;
  1503.     }
  1504.   if (rect->h + rect->y >= y_ceil)
  1505.     {
  1506.       rect->h = y_ceil - rect->y;
  1507.     }
  1508.   cliprectc = 0;
  1509.   collect_clipping (rect);
  1510.   ++clipcnt;
  1511. }
  1512.  
  1513.  
  1514. #ifdef __STDC__
  1515. static void 
  1516. place_text (xx_IntRectangle out, struct display *disp, struct cell_display *cd, XFontStruct *font, char *string)
  1517. #else
  1518. static void 
  1519. place_text (out, disp, cd, font, string)
  1520.      xx_IntRectangle out;
  1521.      struct display *disp;
  1522.      struct cell_display *cd;
  1523.      XFontStruct *font;
  1524.      char *string;
  1525. #endif
  1526. {
  1527.   int *widths = disp->widths;
  1528.   int *heights = disp->heights;
  1529.   int *colx = disp->colx;
  1530.   int *rowy = disp->rowy;
  1531.   struct rng *range = &disp->range;
  1532.   int hout = font->ascent + font->descent;
  1533.   int wout = XTextWidth (font, string, strlen (string));
  1534.   int ci = cd->c - range->lc;
  1535.   int ri = cd->r - range->lr;
  1536.   int yout = rowy[ri] + heights[ri] - (font->ascent + font->descent);
  1537.   int xout;
  1538.   switch (cd->justification)
  1539.     {
  1540.     default:
  1541.     case JST_LFT:
  1542.       xout = colx[ci];
  1543.       break;
  1544.     case JST_RGT:
  1545.       xout = colx[ci] + widths[ci] - 1 - wout;
  1546.       break;
  1547.     case JST_CNT:
  1548.       xout = colx[ci] + (widths[ci] - wout) / 2;
  1549.       break;
  1550.     }
  1551.   xx_IRinit (out, xout, yout, wout, hout);
  1552. }
  1553.  
  1554.  
  1555.  
  1556. #ifdef __STDC__
  1557. static void
  1558. x_metric (struct cell_display *cd, struct display *disp)
  1559. #else
  1560. static void
  1561. x_metric (cd, disp)
  1562.      struct cell_display *cd;
  1563.      struct display *disp;
  1564. #endif
  1565. {
  1566.   struct x_window *xw = (struct x_window *) disp->vdata;
  1567.   Xport port = xw->port;
  1568.   if (!cd->unclipped)
  1569.     xx_IRinit (&cd->goal, 0, 0, 0, 0);
  1570.   else
  1571.     {
  1572.       struct cell_gc *cgc = cell_gc (port, cd->font, 0);
  1573.       place_text (&cd->goal, disp, cd, cgc->font, cd->unclipped);
  1574.     }
  1575. }
  1576.  
  1577.  
  1578.  
  1579. #ifdef __STDC__
  1580. static struct x_window *
  1581. x_win (Xport port, struct window *win, int rebuild)
  1582. #else
  1583. static struct x_window *
  1584. x_win (port, win, rebuild)
  1585.      Xport port;
  1586.      struct window *win;
  1587.      int rebuild;
  1588. #endif
  1589. {
  1590.   struct x_window *xw;
  1591.   
  1592.   for (xw = port->xwins; xw && xw->win != win; xw = xw->next);
  1593.   
  1594.   if (xw && !rebuild)
  1595.     return xw;
  1596.   
  1597.   if (xw)
  1598.     {
  1599.       free_display (&xw->display);
  1600.     }
  1601.   else
  1602.     {
  1603.       xw = (struct x_window *) ck_malloc (sizeof (*xw));
  1604.       xw->next = port->xwins;
  1605.       port->xwins = xw;
  1606.       xw->port = port;
  1607.     }
  1608.   xw->win = win;
  1609.   build_display (&xw->display, &win->screen, x_metric, xw);
  1610.   xw->label_damage = 1;
  1611.   xw->layout_needed = new_display;
  1612.   port->redisp_needed = 1;
  1613.   return xw;
  1614. }
  1615.  
  1616. #ifdef __STDC__
  1617. static void
  1618. flush_x_windows (Xport port)
  1619. #else
  1620. static void
  1621. flush_x_windows (port)
  1622.      Xport port;
  1623. #endif
  1624. {
  1625.   while (port->xwins)
  1626.     {
  1627.       struct x_window * xw = port->xwins;
  1628.       free_display (&xw->display);
  1629.       port->xwins = xw->next;
  1630.       free (xw);
  1631.       port->redisp_needed = 1;
  1632.     }
  1633. }
  1634.  
  1635.  
  1636.  
  1637.  
  1638. #ifdef __STDC__
  1639. static void
  1640. record_damage (Xport port, int x, int y, int w, int h)
  1641. #else
  1642. static void
  1643. record_damage (port, x, y, w, h)
  1644.      Xport port;
  1645.      int x;
  1646.      int y;
  1647.      int w;
  1648.      int h;
  1649. #endif
  1650. {
  1651.   struct x_window *xwin = port->xwins;
  1652.   
  1653.   if (port->input_view.current_info)
  1654.     {
  1655.       port->input_view.info_redraw_needed = 1;
  1656.       return;
  1657.     }
  1658.  
  1659.   if (text_lines)
  1660.     {
  1661.       text_damaged = 1;
  1662.       return;
  1663.     }
  1664.   
  1665.   while (xwin)
  1666.     {
  1667.       struct window *win = xwin->win;
  1668.       record_display_damage (&xwin->display,
  1669.                  x - win->win_over,
  1670.                  y - win->win_down,
  1671.                  w, h);
  1672.       port->redisp_needed = 1;
  1673.       if (   (   (x + w >= win->win_over - win_label_cols(win, win->screen.hr))
  1674.           && (x <= win->win_over)
  1675.           && (y + h >= win->win_down - win_label_rows(win))
  1676.           && (y <= win->win_down + display_height(&xwin->display)))
  1677.       || (   (y + h >= win->win_down - win_label_rows(win))
  1678.           && (y <= win->win_down)
  1679.           && (x + w >= win->win_over - win_label_cols(win, win->screen.hr))
  1680.           && (x <= win->win_over + display_width(&xwin->display))))
  1681.     xwin->label_damage = 1;
  1682.       xwin = xwin->next;
  1683.     }
  1684.  
  1685.   if (((input + input_rows) >= y) && (input <= y + h))
  1686.     port->input_view.redraw_needed = FULL_REDRAW;
  1687. }
  1688.  
  1689.  
  1690.  
  1691. #ifdef __STDC__
  1692. static void
  1693. xio_pr_cell_win (struct window *win, CELLREF r, CELLREF c, CELL *cp)
  1694. #else
  1695. static void
  1696. xio_pr_cell_win (win, r, c, cp)
  1697.      struct window *win;
  1698.      CELLREF r;
  1699.      CELLREF c;
  1700.      CELL *cp;
  1701. #endif
  1702. {
  1703.   struct x_window *xwin = x_win (thePort, win, 0);
  1704.   struct display *disp = &xwin->display;
  1705.   
  1706.   if (pr_display_cell (disp, r, c, cp))
  1707.     {
  1708.       thePort->redisp_needed = 1;
  1709.       if (!xwin->layout_needed)
  1710.     xwin->layout_needed = damaged_display;
  1711.     }
  1712. }
  1713.  
  1714.  
  1715. #ifdef __STDC__
  1716. static void
  1717. xio_repaint_win (struct window *win)
  1718. #else
  1719. static void
  1720. xio_repaint_win (win)
  1721.      struct window *win;
  1722. #endif
  1723. {
  1724.   x_win (thePort, win, 1);
  1725.   XFillRectangle (thePort->dpy, thePort->window, thePort->neutral_gc,
  1726.           win->win_over, win->win_down, win->numc, win->numr);
  1727.   record_damage (thePort, win->win_over, win->win_down, win->numc, win->numr);
  1728. }
  1729.  
  1730.  
  1731.  
  1732. #ifdef __STDC__
  1733. static void
  1734. xio_repaint (void)
  1735. #else
  1736. static void
  1737. xio_repaint ()
  1738. #endif
  1739. {
  1740.   struct window *win;
  1741.   if (thePort->input_view.current_info)
  1742.     {
  1743.       thePort->input_view.info_redraw_needed = 1;
  1744.       return;
  1745.     }
  1746.   flush_x_windows (thePort);
  1747.   for (win = wins; win < &wins[nwin]; win++)
  1748.     xio_repaint_win (win);
  1749. }
  1750.  
  1751.  
  1752. #ifdef __STDC__
  1753. static void
  1754. draw_cell (struct x_window *xwin, struct cell_display *cd_passed, int cursor)
  1755. #else
  1756. static void
  1757. draw_cell (xwin, cd_passed, cursor)
  1758.      struct x_window *xwin;
  1759.      struct cell_display *cd_passed;
  1760.      int cursor;
  1761.      
  1762. #endif
  1763. {
  1764.   struct cell_display *cd = cd_passed->used_by;
  1765.   Xport port = xwin->port;
  1766.   struct window *win = xwin->win;
  1767.   int ov = win->win_over;
  1768.   int dn = win->win_down;
  1769.   CELLREF r = cd->r;
  1770.   CELLREF c = cd->c;
  1771.   struct display *disp = &xwin->display;
  1772.   int *rowy = disp->rowy;
  1773.   int *colx = disp->colx;
  1774.   int *widths = disp->widths;
  1775.   int *heights = disp->heights;
  1776.   struct cell_gc *cgc;
  1777.   int ri = r - disp->range.lr;
  1778.   int ci = c - disp->range.lc;
  1779.   
  1780.   if (!(widths[ci] && heights[ri]))
  1781.     return;
  1782.   
  1783.   if (!cd->unclipped)
  1784.     {
  1785.       cgc = cell_gc (port, default_font(), !cursor);
  1786.       XFillRectangle (port->dpy, port->window, cgc->gc,
  1787.               colx[ci] + ov, rowy[ri] + dn,
  1788.               widths[ci], heights[ri]);
  1789.       return;
  1790.     }
  1791.   
  1792.   cgc = cell_gc (port, cd->font, cursor);
  1793.   {
  1794.     int isclipped;
  1795.     char *str;
  1796.     struct xx_sIntRectangle *strbox;
  1797.     
  1798.     isclipped = !xx_IRencloses_width (&cd->layout, &cd->goal);
  1799.     if (!isclipped)
  1800.       {
  1801.     str = cd->unclipped;
  1802.     strbox = &cd->goal;
  1803.       }
  1804.     else
  1805.       {
  1806.     if (!cd->clipped)
  1807.       {
  1808.         int chr_scale = XTextWidth (cgc->font, "8", 1);
  1809.         int w_avail = xx_IRw (&cd->layout) / chr_scale;
  1810.         int cell_wid = widths[ci] / chr_scale;
  1811.         CELL *cp = find_cell (r, c);
  1812.         cd->clipped =
  1813.           ck_savestr (adjust_prc (cd->unclipped, cp, w_avail, cell_wid,
  1814.                       cd->justification));
  1815.         place_text (&cd->clip, disp, cd, cgc->font, cd->clipped);
  1816.       }
  1817.     str = cd->clipped;
  1818.     strbox = &cd->clip;
  1819.       }
  1820.     XDrawImageString (port->dpy, port->window, cgc->gc,
  1821.               strbox->x + ov, strbox->y + cgc->font->ascent + dn,
  1822.               str, strlen (str));
  1823.     {
  1824.       struct xx_sIntRectangle tofill[4];
  1825.       int fillc;
  1826.       
  1827.       fillc = xx_IRsubtract (tofill, &cd->layout, strbox);
  1828.       {
  1829.     XGCValues v;
  1830.     v.foreground = cursor ? port->fg_color_pixel : port->bg_color_pixel;
  1831.     v.background = cursor ? port->bg_color_pixel : port->fg_color_pixel;
  1832.     XChangeGC (port->dpy, cgc->gc, GCForeground | GCBackground, &v);
  1833.     cgc->cursor = !cursor;
  1834.       }
  1835.       while (fillc--)
  1836.     XFillRectangle (port->dpy, port->window, cgc->gc,
  1837.             tofill[fillc].x + ov, tofill[fillc].y + dn,
  1838.             tofill[fillc].w, tofill[fillc].h);
  1839.     }
  1840.   }
  1841. }
  1842.  
  1843.  
  1844. /* Cell values */
  1845.  
  1846. #ifdef __STDC__
  1847. static void
  1848. set_cursor (int on)
  1849. #else
  1850. static void
  1851. set_cursor (on)
  1852.      int on;
  1853. #endif
  1854. {
  1855.   struct x_window *xwin = x_win (thePort, cwin, 0);
  1856.   struct display *disp = &xwin->display;
  1857.   int *rowy = disp->rowy;
  1858.   int *colx = disp->colx;
  1859.   int *widths = disp->widths;
  1860.   int *heights = disp->heights;
  1861.   int ri = curow - disp->range.lr;
  1862.   int ci = cucol - disp->range.lc;
  1863.   int ov = xwin->win->win_over;
  1864.   int dn = xwin->win->win_down;
  1865.   struct cell_display *cd = cell_display_of (disp, curow, cucol);
  1866.   struct xx_sIntRectangle clip;
  1867.  
  1868.   /* The cursor might not even be visible.  Though commands should never leave
  1869.    * the user in such a state, it can happen in several ways transiently.
  1870.    */
  1871.   if (!cd)
  1872.     return;
  1873.  
  1874.   thePort->cursor_visible = on;
  1875.   
  1876.   if (xwin->layout_needed == new_display)
  1877.     return;
  1878.   
  1879.   if (cd->used_by == cd)
  1880.     {
  1881.       clip = cd->layout;
  1882.       clip.x += ov;
  1883.       clip.y += dn;
  1884.     }
  1885.   else
  1886.     xx_IRinit (&clip,
  1887.            colx[ci] + ov, rowy[ri] + dn,
  1888.            widths[ci], heights[ri]);
  1889.   clip_to_intrectangle (xwin, &clip);
  1890.   draw_cell (xwin, cd, on);
  1891. }
  1892.  
  1893.  
  1894. #ifdef __STDC__
  1895. static void
  1896. xio_hide_cell_cursor (void)
  1897. #else
  1898. static void
  1899. xio_hide_cell_cursor ()
  1900. #endif
  1901. {
  1902.   if (thePort->cursor_visible)
  1903.     set_cursor (0);
  1904. }
  1905.  
  1906. #ifdef __STDC__
  1907. static void
  1908. xio_display_cell_cursor (void)
  1909. #else
  1910. static void
  1911. xio_display_cell_cursor ()
  1912. #endif
  1913. {
  1914.   if (!thePort->cursor_visible)
  1915.     {
  1916.       if (   (curow < cwin->screen.lr)
  1917.       || (cucol < cwin->screen.lc)
  1918.       || (curow > cwin->screen.hr)
  1919.       || (cucol > cwin->screen.hc))
  1920.     io_recenter_cur_win ();
  1921.       set_cursor (1);
  1922.     }
  1923. }
  1924.  
  1925.  
  1926. static int xx[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
  1927.  
  1928.  
  1929. #ifdef __STDC__
  1930. static void
  1931. draw_labels (void)
  1932. #else
  1933. static void
  1934. draw_labels ()
  1935. #endif
  1936. {
  1937.   struct x_window *xwin;
  1938.   XRectangle rect;
  1939.   for (xwin = thePort->xwins; xwin; xwin = xwin->next)
  1940.     if (xwin->win->lh_wid && xwin->label_damage)
  1941.       {
  1942.     XGCValues gcv;
  1943.     struct window *win = xwin->win;
  1944.     int wid2 = win->lh_wid / 2;
  1945.     if (xx[0]) {
  1946.       XFillRectangle (thePort->dpy, thePort->window,
  1947.               thePort->label_standout_gc,
  1948.               win->win_over - win->lh_wid,
  1949.               win->win_down - label_rows,
  1950.               wid2, label_rows);
  1951.     };
  1952.     gcv.line_width = win->lh_wid;
  1953.     gcv.cap_style = CapRound;
  1954.     XChangeGC (thePort->dpy, thePort->label_gc,
  1955.            GCLineWidth | GCCapStyle, &gcv);
  1956.     if (xx[1]) {
  1957.       XDrawLine (thePort->dpy, thePort->window, thePort->label_gc,
  1958.              win->win_over - wid2,
  1959.              win->win_down - label_rows + wid2,
  1960.              win->win_over - wid2,
  1961.              win->win_down + win->numr - wid2);
  1962.       
  1963.     };
  1964.     gcv.cap_style = CapButt;
  1965.     XChangeGC (thePort->dpy, thePort->label_gc, GCCapStyle, &gcv);
  1966.     if (xx[2]) {
  1967.       XDrawLine (thePort->dpy, thePort->window, thePort->label_gc,
  1968.              win->win_over - wid2,
  1969.              win->win_down + wid2,
  1970.              win->win_over - wid2,
  1971.              win->win_down + win->numr);
  1972.     };
  1973.     
  1974.     if (xx[3]) {
  1975.       XFillRectangle (thePort->dpy, thePort->window, thePort->label_gc,
  1976.               win->win_over - wid2,
  1977.               win->win_down - label_rows,
  1978.               win->numc + wid2,
  1979.               label_rows);
  1980.     };
  1981.     
  1982.     rect.x = 0;
  1983.     rect.y = 0;
  1984.     rect.width = scr_cols;
  1985.     rect.height = scr_lines;
  1986.     XSetClipRectangles (thePort->dpy, thePort->label_standout_gc,
  1987.                 0, 0, &rect, 1, YXBanded);
  1988.     {
  1989.       char buf[100];
  1990.       CELLREF cr;
  1991.       int x;
  1992.       int len;
  1993.       
  1994.       sprintf (buf, "#%d", 1 + win - wins);
  1995.       for (x = len = 0; buf[x]; ++x)
  1996.         {
  1997.           int cwid = XTextWidth (thePort->label_font, buf, 1);
  1998.           if (cwid + len > wid2)
  1999.         break;
  2000.           len += cwid;
  2001.         }
  2002.       XDrawImageString (thePort->dpy, thePort->window,
  2003.                 thePort->label_standout_gc,
  2004.                 win->win_over - wid2,
  2005.                 win->win_down - thePort->label_font->descent,
  2006.                 buf, x);
  2007.       
  2008.       rect.x = win->win_over - win->lh_wid;
  2009.       rect.y = win->win_down;
  2010.       rect.width = win->lh_wid;
  2011.       rect.height = win->numr;
  2012.       XSetClipRectangles (thePort->dpy, thePort->label_standout_gc,
  2013.                   0, 0, &rect, 1, YXBanded);
  2014.       
  2015.       x = win->win_down + thePort->label_font->ascent;
  2016.       for (cr = win->screen.lr; cr <= win->screen.hr; ++cr)
  2017.         {
  2018.           int hgt = get_scaled_height (cr);
  2019.           if (hgt)
  2020.         {
  2021.           if (a0)
  2022.             sprintf (buf, "%d", cr);
  2023.           else
  2024.             sprintf (buf, "R%d", cr);
  2025.           XDrawImageString (thePort->dpy, thePort->window,
  2026.                     thePort->label_standout_gc,
  2027.                     win->win_over - win->lh_wid, x,
  2028.                     buf, strlen (buf));
  2029.           x += hgt;
  2030.         }
  2031.           if (cr == MAX_ROW)
  2032.         break;
  2033.         }
  2034.       rect.x = 0;
  2035.       rect.y = 0;
  2036.       rect.width = scr_cols;
  2037.       rect.height = scr_lines;
  2038.       XSetClipRectangles (thePort->dpy, thePort->label_standout_gc,
  2039.                   0, 0, &rect, 1, YXBanded);
  2040.       
  2041.       x = win->win_over;
  2042.       for (cr = win->screen.lc; cr <= win->screen.hc; ++cr)
  2043.         {
  2044.           int wid = get_scaled_width (cr);
  2045.           if (wid > win->numc)
  2046.         wid = win->numc;
  2047.           if (wid)
  2048.         {
  2049.           int txtwid;
  2050.           char *ptr;
  2051.           if (a0)
  2052.             ptr = col_to_str (cr);
  2053.           else
  2054.             {
  2055.               ptr = buf;
  2056.               sprintf (ptr, "C%u", cr);
  2057.             }
  2058.           txtwid = XTextWidth (thePort->label_font, ptr, strlen (ptr));
  2059.           if (txtwid > wid - thePort->label_font->max_bounds.width)
  2060.             {
  2061.               int txtlen =
  2062.             ((wid - thePort->label_font->max_bounds.width)
  2063.              / XTextWidth (thePort->label_font, "#", 1));
  2064.               txtwid = txtlen * XTextWidth (thePort->label_font,
  2065.                             "#", 1);
  2066.               buf[txtlen] = 0;
  2067.               while (txtlen)
  2068.             buf[txtlen--] = '#';
  2069.               ptr = buf;
  2070.             }
  2071.           XDrawImageString (thePort->dpy, thePort->window,
  2072.                     thePort->label_standout_gc,
  2073.                     x + (wid - txtwid) / 2,
  2074.                     (win->win_down
  2075.                      - thePort->label_font->descent),
  2076.                     ptr, strlen (ptr));
  2077.           x += wid;
  2078.         }
  2079.           if (cr == MAX_COL)
  2080.         break;
  2081.         }
  2082.     }
  2083.     xwin->label_damage = 0;
  2084.       }
  2085. }
  2086.  
  2087.  
  2088. /* Refresh the existing image. */
  2089.  
  2090.  
  2091. #ifdef __STDC__
  2092. static void
  2093. xio_redisp (void)
  2094. #else
  2095. static void
  2096. xio_redisp ()
  2097. #endif
  2098. {
  2099.   static int was_text = 0;
  2100.   if (thePort->input_view.current_info)
  2101.     {
  2102.       if (!was_text)
  2103.     thePort->input_view.redraw_needed = FULL_REDRAW;
  2104.  
  2105.       if (thePort->input_view.redraw_needed != NO_REDRAW)
  2106.     xio_redraw_input ();
  2107.  
  2108.       if (thePort->input_view.info_redraw_needed)
  2109.     {
  2110.       int ipos = thePort->input_view.info_pos;
  2111.       int top = ipos + (scr_lines - input_rows) / info_rows - 1;
  2112.       int ypos;
  2113.       XTextItem text;
  2114.  
  2115.       if (top >= thePort->input_view.current_info->len)
  2116.         top = thePort->input_view.current_info->len - 1;
  2117.  
  2118.       ypos = input_rows;
  2119.  
  2120.       text.font = thePort->text_line_font->fid;
  2121.       while (ipos <= top)
  2122.         {
  2123.           text.chars = thePort->input_view.current_info->text[ipos];
  2124.           text.nchars = strlen (text.chars);
  2125.           draw_text_item (thePort, 0, ypos, scr_cols, input_rows,
  2126.                   thePort->text_line_font, thePort->text_line_gc,
  2127.                   &text, 0);
  2128.           ypos += info_rows;
  2129.           ++ipos;
  2130.         }
  2131.       XFillRectangle (thePort->dpy, thePort->window,
  2132.               thePort->neutral_gc, 0, ypos,
  2133.               scr_cols, scr_lines - ypos - 1);
  2134.       thePort->input_view.redraw_needed = FULL_REDRAW;
  2135.       xio_redraw_input ();
  2136.       thePort->input_view.info_redraw_needed = 0;
  2137.       was_text = 1;
  2138.     }
  2139.     }
  2140.   else
  2141.     {
  2142.       struct x_window *xwin;
  2143.       if (was_text)
  2144.     {
  2145.       thePort->input_view.info_redraw_needed = 0;
  2146.       was_text = 0;
  2147.       io_repaint ();
  2148.     }
  2149.       else
  2150.     {
  2151.       struct rng * rng = &cwin->screen;
  2152.       if (   (curow > rng->hr)
  2153.           || (curow < rng->lr)
  2154.           || (cucol > rng->hc)
  2155.           || (cucol < rng->lc))
  2156.         io_recenter_cur_win ();
  2157.     }
  2158.       thePort->redisp_needed = 0;
  2159.       if (thePort->redisp_needed != NO_REDRAW)
  2160.     xio_redraw_input ();
  2161.       draw_status ();
  2162.       draw_labels ();
  2163.       for (xwin = thePort->xwins; xwin; xwin = xwin->next)
  2164.     {
  2165.       struct display *disp = &xwin->display;
  2166.       int ov = xwin->win->win_over;
  2167.       int dn = xwin->win->win_down;
  2168.       struct cell_display * cd;
  2169.       struct cell_display * cursor_cd = 0;
  2170.       int must_draw_cursor;
  2171.       
  2172.       if (xwin->layout_needed)
  2173.         {
  2174.           layout (disp);
  2175.           xwin->layout_needed = 0;
  2176.         }
  2177.       
  2178.       /* If the cursor cell has been damaged, 
  2179.        * it will be redrawn.  However, if the 
  2180.        * cursor cell is empty, then redrawing
  2181.        * some other cell might damage the cursor.
  2182.        * This watches for that condition and
  2183.        * redraws the cursor if it occurs.
  2184.        */
  2185.       must_draw_cursor = 0;
  2186.       if (thePort->cursor_visible
  2187.           && (xwin->win == cwin)
  2188.           && (curow >= disp->range.lr)
  2189.           && (curow <= disp->range.hr)
  2190.           && (cucol >= disp->range.lc)
  2191.           && (cucol <= disp->range.hc))
  2192.         {
  2193.           cursor_cd = cell_display_of (disp, curow, cucol);
  2194.           /* If the cursor cell is not empty, we never have
  2195.            * to explicitly redraw the cursor.
  2196.            */
  2197.           if (cursor_cd->used_by == cursor_cd)
  2198.         cursor_cd = 0;
  2199.         }
  2200.       
  2201.       cd = disp->damaged;
  2202.       while (cd != (struct cell_display *) disp)
  2203.         {
  2204.           struct xx_sIntRectangle clip;
  2205.           struct cell_display *owner = cd->used_by;
  2206.           clip = owner->layout;
  2207.           clip.x += ov;
  2208.           clip.y += dn;
  2209.           clip_to_intrectangle (xwin, &clip);
  2210.           if (cursor_cd && (cd->used_by == cursor_cd->used_by))
  2211.         must_draw_cursor = 1;
  2212.           draw_cell (xwin, owner,
  2213.              (thePort->cursor_visible
  2214.               && (xwin->win == cwin)
  2215.               && (owner->r == curow)
  2216.               && (owner->c == cucol)));
  2217.           {    
  2218.         struct cell_display *cdt = cd;
  2219.         cd = cd->next_damaged;
  2220.         cdt->next_damaged = 0;
  2221.           }
  2222.         }
  2223.       disp->damaged = (struct cell_display *) disp;
  2224.       if (must_draw_cursor)
  2225.         set_cursor (1);
  2226.     }
  2227.     }
  2228. }
  2229.  
  2230.  
  2231.  
  2232.  
  2233. #ifdef __STDC__
  2234. static XFontStruct *
  2235. reasonable_font (Xport port, char *name)
  2236. #else
  2237. static XFontStruct *
  2238. reasonable_font (port, name)
  2239.      Xport port;
  2240.      char *name;
  2241. #endif
  2242. {
  2243.   XFontStruct *f = XLoadQueryFont (port->dpy, name);
  2244.   
  2245.   if (!f)
  2246.     {
  2247.       printf("(warning) Font %s could not be loaded.\n", name);
  2248.       f = XLoadQueryFont (port->dpy, default_font_name);
  2249.       if (!f)
  2250.     {
  2251.       panic ("Default font %s could not be loaded.\n",
  2252.          default_font_name);
  2253.       exit(0);
  2254.     }
  2255.     }
  2256.   return f;
  2257. }
  2258.  
  2259. #ifdef __STDC__
  2260. extern void 
  2261. xio_open_display (void)
  2262. #else
  2263. extern void 
  2264. xio_open_display ()
  2265. #endif
  2266. {
  2267.   XGCValues gcv;
  2268.   XWMHints wmhints;
  2269.   
  2270.   thePort = (Xport) ck_malloc (sizeof (*thePort));
  2271.   thePort->cursor_visible = 1;
  2272.   thePort->redisp_needed = 1;
  2273.   thePort->xwins = 0;
  2274.   
  2275.   thePort->dpy = theDisplay;
  2276.  
  2277.   bzero (&thePort->input_view, sizeof (struct input_view));
  2278.   thePort->input_view.prompt_metric = x_input_metric;
  2279.   thePort->input_view.input_metric = x_input_metric;
  2280.   
  2281.   thePort->screen = DefaultScreen (thePort->dpy);
  2282.   thePort->color_map = DefaultColormap (thePort->dpy, thePort->screen);
  2283.   
  2284.   if (default_fg_color_name && 
  2285.       XParseColor (thePort->dpy, thePort->color_map, default_fg_color_name, &thePort->fg_color) &&
  2286.       XAllocColor(thePort->dpy, thePort->color_map, &thePort->fg_color))
  2287.     thePort->fg_color_pixel = thePort->fg_color.pixel;
  2288.   else
  2289.     if (default_fg_color_name && !stricmp (default_fg_color_name, "black"))
  2290.       thePort->fg_color_pixel = BlackPixel (thePort->dpy, thePort->screen);
  2291.     else
  2292.       if (default_fg_color_name && !stricmp (default_fg_color_name, "white"))
  2293.     thePort->fg_color_pixel = WhitePixel (thePort->dpy, thePort->screen);
  2294.   
  2295.   if (default_bg_color_name && 
  2296.       XParseColor (thePort->dpy, thePort->color_map, default_bg_color_name, &thePort->bg_color) &&
  2297.       XAllocColor(thePort->dpy, thePort->color_map, &thePort->bg_color))
  2298.     thePort->bg_color_pixel = thePort->bg_color.pixel;
  2299.   else
  2300.     if (default_bg_color_name && !stricmp (default_bg_color_name, "black"))
  2301.       thePort->bg_color_pixel = BlackPixel (thePort->dpy, thePort->screen);
  2302.     else
  2303.       if (default_bg_color_name && !stricmp (default_bg_color_name, "white"))
  2304.     thePort->fg_color_pixel = WhitePixel (thePort->dpy, thePort->screen);
  2305.   
  2306.   thePort->window =
  2307.     XCreateSimpleWindow (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2308.              geom_x, geom_y, geom_w, geom_h,
  2309.              1, thePort->fg_color_pixel, thePort->bg_color_pixel);
  2310.   XStoreName (thePort->dpy, thePort->window, oleo_version_string);
  2311.   wmhints.flags = InputHint;
  2312.   wmhints.input = True;
  2313.   XSetWMHints(thePort->dpy, thePort->window, &wmhints);
  2314.  
  2315.   thePort->wm_delete_window = XInternAtom(thePort->dpy, "WM_DELETE_WINDOW", False);
  2316.   (void) XSetWMProtocols( thePort->dpy, thePort->window, &thePort->wm_delete_window, 1);
  2317.   
  2318.   gcv.foreground = thePort->bg_color_pixel;
  2319.   gcv.background = thePort->bg_color_pixel;
  2320.   thePort->neutral_gc =
  2321.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2322.            (GCForeground | GCBackground), &gcv);
  2323.   
  2324.   gcv.foreground = thePort->fg_color_pixel;
  2325.   gcv.background = thePort->bg_color_pixel;
  2326.   thePort->normal_gc =
  2327.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2328.            (GCForeground | GCBackground), &gcv);
  2329.   
  2330.   gcv.foreground = thePort->bg_color_pixel;
  2331.   gcv.background = thePort->fg_color_pixel;
  2332.   thePort->standout_gc =
  2333.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2334.            (GCForeground | GCBackground), &gcv);
  2335.   
  2336.   thePort->input_font = reasonable_font (thePort, input_font_name);
  2337.   gcv.font = thePort->input_font->fid;
  2338.   gcv.foreground = thePort->fg_color_pixel;
  2339.   gcv.background = thePort->bg_color_pixel;
  2340.   thePort->input_gc =
  2341.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2342.            (GCForeground | GCBackground | GCFont), &gcv);
  2343.   
  2344.   gcv.foreground = thePort->bg_color_pixel;
  2345.   gcv.background = thePort->fg_color_pixel;
  2346.   thePort->standout_input_gc =
  2347.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2348.            (GCForeground | GCBackground | GCFont), &gcv);
  2349.   
  2350.   gcv.foreground = thePort->fg_color_pixel;
  2351.   gcv.background = thePort->bg_color_pixel;
  2352.   thePort->status_font = reasonable_font (thePort, status_font_name);
  2353.   gcv.font = thePort->status_font->fid;
  2354.   thePort->status_gc =
  2355.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2356.            (GCForeground | GCBackground | GCFont), &gcv);
  2357.   
  2358.   thePort->label_font = reasonable_font (thePort, label_font_name);
  2359.   gcv.font = thePort->label_font->fid;
  2360.   gcv.cap_style = CapRound;
  2361.   thePort->label_gc =
  2362.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2363.            (GCForeground | GCBackground | GCFont | GCCapStyle), &gcv);
  2364.   
  2365.   gcv.background = thePort->fg_color_pixel;
  2366.   gcv.foreground = thePort->bg_color_pixel;
  2367.   thePort->label_standout_gc =
  2368.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2369.            (GCForeground | GCBackground | GCFont | GCCapStyle), &gcv);
  2370.   
  2371.   gcv.background = thePort->bg_color_pixel;
  2372.   gcv.foreground = thePort->fg_color_pixel;
  2373.   thePort->text_line_font = reasonable_font (thePort, text_line_font_name);
  2374.   gcv.font = thePort->text_line_font->fid;
  2375.   thePort->text_line_gc =
  2376.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2377.            (GCForeground | GCBackground | GCFont), &gcv);
  2378.  
  2379.   info_rows = (thePort->text_line_font->max_bounds.ascent
  2380.            + thePort->text_line_font->max_bounds.descent);
  2381.   
  2382.   gcv.background = thePort->fg_color_pixel;
  2383.   gcv.foreground = thePort->bg_color_pixel;
  2384.   thePort->text_line_standout_gc =
  2385.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2386.            (GCForeground | GCBackground | GCFont), &gcv);
  2387.   
  2388.   gcv.background = thePort->fg_color_pixel;
  2389.   gcv.foreground = thePort->bg_color_pixel;
  2390.   thePort->text_line_standout_gc =
  2391.     XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2392.            (GCForeground | GCBackground | GCFont), &gcv);
  2393.   
  2394.   gcv.background = thePort->bg_color_pixel;
  2395.   gcv.foreground = thePort->fg_color_pixel;
  2396.   
  2397.   {
  2398.     int x;
  2399.     for (x = 0; x < GC_CACHE_SIZE; ++x)
  2400.       {
  2401.     struct cell_gc *cg =
  2402.       (struct cell_gc *) ck_malloc (sizeof (struct cell_gc));
  2403.     cg->font_name = 0;
  2404.     cg->font = 0;
  2405.     cg->clipped_to = 0;
  2406.     cg->cursor = 0;
  2407.     cg->gc = XCreateGC (thePort->dpy, DefaultRootWindow (thePort->dpy),
  2408.                 (GCForeground | GCBackground), &gcv);
  2409.     if (!cell_gc_cache)
  2410.       {
  2411.         cg->next = cg;
  2412.         cg->prev = cg;
  2413.       }
  2414.     else
  2415.       {
  2416.         cg->next = cell_gc_cache;
  2417.         cg->prev = cg->next->prev;
  2418.         cg->next->prev = cg;
  2419.         cg->prev->next = cg;
  2420.       }
  2421.     cell_gc_cache = cg;
  2422.       }
  2423.   }
  2424.   
  2425.   XSelectInput (thePort->dpy, thePort->window,
  2426.         (ExposureMask | StructureNotifyMask | KeyPressMask
  2427.          | ButtonPressMask));
  2428.   
  2429.   io_init_windows (geom_h, geom_w, 1, 2,
  2430.            thePort->input_font->ascent + thePort->input_font->descent,
  2431.            (thePort->status_font->ascent
  2432.             + thePort->status_font->descent),
  2433.            thePort->label_font->ascent + thePort->label_font->descent,
  2434.            thePort->label_font->max_bounds.width);
  2435.   x11_opened = 1;
  2436.   
  2437.   {
  2438.     struct cell_gc *cgc = cell_gc (thePort, default_font(), 0);
  2439.     height_scale = cgc->font->ascent + cgc->font->descent;
  2440.     width_scale = XTextWidth (cgc->font, "M", 1);
  2441.   }
  2442.  
  2443.   /* Setup the arrow keys.  Modifiers effect the last character
  2444.    * of the translation.
  2445.    */
  2446.   {
  2447.     static KeySym meta_shift_ctrl[]
  2448.       = {Mod1MapIndex, ShiftMapIndex, ControlMapIndex };
  2449. #define shift_ctrl &meta_shift_ctrl[1]
  2450. #define ctrl  &meta_shift_ctrl[2]
  2451.     static KeySym meta_shift[] = {Mod1MapIndex, ShiftMapIndex};
  2452. #define shift &meta_shift[1]
  2453.     static KeySym ctrl_meta[] = {ControlMapIndex, Mod1MapIndex};
  2454. #define meta &ctrl_meta[1]
  2455.  
  2456.     static KeySym * mod_combos [] =
  2457.       {
  2458.     0,
  2459.     ctrl, shift, meta,
  2460.     shift_ctrl, ctrl_meta, meta_shift,
  2461.     meta_shift_ctrl
  2462.       };
  2463.     static char meta_modp [] = { 0, 0, 0, 1, 0, 1, 1, 1 };
  2464.     static char base_char [] =
  2465.       {
  2466.     'A', '\001', 'a', 'A',
  2467.     '\001', '\001', 'a', '\001'
  2468.       };
  2469.     /* In ansi order: */
  2470.     static KeySym arrows[] = {XK_Up, XK_Down, XK_Left, XK_Right};
  2471.     int arrow;
  2472.  
  2473.     for (arrow = 0; arrow < 4; ++arrow)
  2474.       {
  2475.     int mod;
  2476.     for (mod = 0; mod < 8; ++mod)
  2477.       {
  2478.         char string[10];
  2479.         sprintf (string, "\033[%s%c",
  2480.              meta_modp[mod] ? "\033" : "",
  2481.              base_char[mod] + arrow);
  2482.         XRebindKeysym (thePort->dpy, arrows[arrow],
  2483.                mod_combos[mod], (mod + 2) / 3,
  2484.                string, strlen(string));
  2485.       }
  2486.       }
  2487.   }
  2488.   
  2489.   XMapWindow (thePort->dpy, thePort->window);
  2490. }
  2491.  
  2492.  
  2493. #ifdef __STDC__
  2494. extern void
  2495. xio_close_display (void)
  2496. #else
  2497. extern void
  2498. xio_close_display ()
  2499. #endif
  2500. {
  2501.   XCloseDisplay (thePort->dpy);
  2502.   x11_opened = 0;
  2503. }
  2504.  
  2505. #ifdef __STDC__
  2506. static void
  2507. xio_flush (void)
  2508. #else
  2509. static void
  2510. xio_flush ()
  2511. #endif
  2512. {
  2513.   XFlush (theDisplay);
  2514. }
  2515.  
  2516.  
  2517.  
  2518.  
  2519. #define _io_open_display xio_open_display
  2520. #define _io_redisp xio_redisp
  2521. #define _io_repaint xio_repaint
  2522. #define _io_repaint_win xio_repaint_win
  2523. #define _io_close_display xio_close_display
  2524. #define _io_input_avail xio_input_avail
  2525. #define _io_scan_for_input xio_scan_for_input
  2526. #define _io_wait_for_input xio_wait_for_input
  2527. #define _io_read_kbd xio_read_kbd
  2528. #define _io_nodelay xio_nodelay
  2529. #define _io_getch xio_getch
  2530. #define _io_bell xio_bell
  2531. #define _io_get_chr xio_get_chr
  2532. #define _io_update_status xio_update_status
  2533. #define _io_info_msg xio_info_msg
  2534. #define _io_error_msg xio_error_msg
  2535. #define _io_fix_input xio_fix_input
  2536. #define _io_move_cursor xio_move_cursor
  2537. #define _io_erase xio_erase
  2538. #define _io_insert xio_insert
  2539. #define _io_over xio_over
  2540. #define _io_flush xio_flush
  2541. #define _io_clear_input_before xio_clear_input_before
  2542. #define _io_clear_input_after xio_clear_input_after
  2543. #define _io_pr_cell_win xio_pr_cell_win
  2544. #define _io_hide_cell_cursor xio_hide_cell_cursor
  2545. #define _io_display_cell_cursor xio_display_cell_cursor
  2546. #define _io_cellize_cursor xio_cellize_cursor
  2547. #define _io_inputize_cursor xio_inputize_cursor
  2548.  
  2549.  
  2550. #ifdef __STDC__
  2551. void
  2552. x11_graphics (void)
  2553. #else
  2554. void
  2555. x11_graphics ()
  2556. #endif
  2557. {
  2558.   IO_SETUP;
  2559. }
  2560.  
  2561. #ifdef __STDC__
  2562. void
  2563. set_x_default_point_size (int l)
  2564. #else
  2565. void
  2566. set_x_default_point_size (l)
  2567.      int l;
  2568. #endif
  2569. {
  2570.   if (l > 4)
  2571.     {
  2572.       cell_font_point_size = l;
  2573.       {
  2574.     struct cell_gc *cgc = cell_gc (thePort, default_font(), 0);
  2575.     height_scale = cgc->font->ascent + cgc->font->descent;
  2576.     width_scale = cgc->font->max_bounds.width;
  2577.       }
  2578.       io_set_scr_size (scr_lines, scr_cols);
  2579.     }
  2580. }
  2581.  
  2582.  
  2583. #endif /* HAVE_X11_X_H */
  2584.  
  2585.